/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package managedbean;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
///
import entity.RedemptionListEntity;
import entity.RedemptionItemEntity;
import entity.StakeholderEntity;
import entity.BranchEntity;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import util.entityhelper.ULPItemHelper;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.Date;
import javax.ejb.EJB;
import session.stateful.LoyaltyProgramSessionBean;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.ActionEvent;
import javax.faces.event.PhaseEvent;
import org.primefaces.event.FileUploadEvent;
import org.primefaces.event.SelectEvent;

/**
 *
 * @author NGUYEN CONG DAT
 */
@ManagedBean
@SessionScoped
public class StakeholderULPManagerBean {

    @EJB
    private LoyaltyProgramSessionBean loyaltyProgramSessionBean;
    private StakeholderEntity stakeholder;
    private BranchEntity selectedBranch;
    private RedemptionListEntity ULPItem;
    private List<RedemptionListEntity> pendingULPItemApplicationList;
    private List<RedemptionListEntity> ULPItemApplicationList;
    private List<ULPItemHelper> expiredULPItemList;
    private List<ULPItemHelper> currentULPItemList;
    private RedemptionListEntity selectedULPItemApplication;
    private ULPItemHelper selectedULPItem;
    private Boolean reloadPage = true;
    private String inputReferenceNumber = "";
    private Boolean voucherExist = false;
    private Boolean enableRedeemVoucher = false;
    private RedemptionItemEntity selectedVoucher;
    private Date inputDateFrom;
    private Date inputDateUntil;
    private List<RedemptionItemEntity> redemptionInPeriodList;
    private boolean displayRedemptions = false;
    private RedemptionItemEntity selectedRedemption;
    private FacesContext ctx = FacesContext.getCurrentInstance();

    /** Creates a new instance of ULPItemManagerBean */
    public StakeholderULPManagerBean() {
        loyaltyProgramSessionBean = new LoyaltyProgramSessionBean();
        stakeholder = (StakeholderEntity) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("stakeholder");
        selectedBranch = (BranchEntity) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("selectedBranch");
        ULPItem = new RedemptionListEntity();
        pendingULPItemApplicationList = new ArrayList<RedemptionListEntity>();
        ULPItemApplicationList = new ArrayList<RedemptionListEntity>();
        expiredULPItemList = new ArrayList<ULPItemHelper>();
        currentULPItemList = new ArrayList<ULPItemHelper>();

        selectedULPItemApplication = new RedemptionListEntity();
        selectedULPItem = new ULPItemHelper(null, null, null);
        selectedVoucher = new RedemptionItemEntity();

    }

    public void createULPItem(ActionEvent event) {
        try {
            System.out.println("Stakeholder ID : " + getStakeholder().getId());
            getLoyaltyProgramSessionBean().stakeholderCreateULPItem(getStakeholder().getId(), getULPItem());
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(
                    FacesMessage.SEVERITY_INFO, "ULP Item Application has been created and sent to TCube", ""));
            setReloadPage(true);
        } catch (Exception e) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(
                    FacesMessage.SEVERITY_ERROR, "An error occurred ! ULPItem application cannot be created", ""));
            e.printStackTrace();
        }
    }

    public void voidULPItemApplication(ActionEvent event) {
        try {
            if (getSelectedULPItemApplication().getStatus().equals("Application Pending")) {
                getLoyaltyProgramSessionBean().voidULPItemApplication(getSelectedULPItemApplication().getId());
                setSelectedULPItemApplication(new RedemptionListEntity());
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(
                        FacesMessage.SEVERITY_INFO, "ULPItem application has been voided", ""));
            } else {
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(
                        FacesMessage.SEVERITY_ERROR, "This ULPItem application cannot be voided", ""));
            }
        } catch (Exception e) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(
                    FacesMessage.SEVERITY_ERROR, "An error occurred ! ULPItem application cannot be voided", ""));
            e.printStackTrace();
        }
    }

    // Initialize list of ULPItem APPLICATIONS For STAKEHOLDERS
    public void initULPItemApplicationList(PhaseEvent event) throws IOException {
        setPendingULPItemApplicationList(getLoyaltyProgramSessionBean().getPendingULPItemApplicationListByStakeholderId(getStakeholder().getId()));
        setULPItemApplicationList(getLoyaltyProgramSessionBean().getULPItemApplicationListByStakeholderId(getStakeholder().getId()));
        // offeredULPItemList = ULPItemSessionBean
    }

    // Initialize list of ULPItems For STAKEHOLDERS
    public void initULPItemList(PhaseEvent event) throws IOException {
        if (checkStakeholder()) {
            setCurrentULPItemList(getLoyaltyProgramSessionBean().getCurrentULPItemsByStakeholderId(getStakeholder().getId()));
            setExpiredULPItemList(getLoyaltyProgramSessionBean().getExpiredULPItemsByStakeholderId(getStakeholder().getId()));
        }
    }

    public void initViewULPItem(PhaseEvent event) throws IOException {
        if (!checkULPItem()) {
            return;
        }
    }

    public void initViewULPItemApplication(PhaseEvent event) throws IOException {
        if (!checkULPItemApplication()) {
            return;
        }
    }

    public void initAddULPItem(PhaseEvent event) throws IOException {
        stakeholder = (StakeholderEntity) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("stakeholder");
        // Check whether stakeholder has logged in or not
        if (stakeholder == null || stakeholder.getId() == null) {
            String serverName = ctx.getExternalContext().getRequestServerName();
            int serverPort = (Integer) ctx.getExternalContext().getSessionMap().get("serverPort");
            String contextPath = ctx.getExternalContext().getRequestContextPath();
            ctx.getExternalContext().redirect("http://" + serverName + ":" + serverPort + contextPath + "/tourist/stakeholder/StakeholderLogin.xhtml");
        }
        if (isReloadPage()) {
            setULPItem(new RedemptionListEntity());
            setReloadPage(false);
        }
    }

    public boolean checkULPItem() throws IOException {
        if (!checkStakeholder()) {
            return false;
        }
        setSelectedULPItem((ULPItemHelper) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("selectedULPItem"));
        if (getSelectedULPItem().getULPItem() == null || getSelectedULPItem().getULPItem().getId() == null) {
              String serverName = ctx.getExternalContext().getRequestServerName();
        int serverPort = (Integer) ctx.getExternalContext().getSessionMap().get("serverPort");
        String contextPath = ctx.getExternalContext().getRequestContextPath();
        ctx.getExternalContext().redirect("http://" + serverName + ":" + serverPort + contextPath + "/stakeholder/StakeholderViewOfferedULPItems.xhtml");
            return false;
        }
        return true;
    }

    public boolean checkULPItemApplication() throws IOException {
        if (!checkStakeholder()) {
            return false;
        }
        setSelectedULPItemApplication((RedemptionListEntity) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("selectedULPItemApplication"));
        if (getSelectedULPItemApplication() == null || getSelectedULPItemApplication().getId() == null) {
                String serverName = ctx.getExternalContext().getRequestServerName();
        int serverPort = (Integer) ctx.getExternalContext().getSessionMap().get("serverPort");
        String contextPath = ctx.getExternalContext().getRequestContextPath();
        ctx.getExternalContext().redirect("http://" + serverName + ":" + serverPort + contextPath + "/stakeholder/StakeholderTrackULPItemApplications.xhtml");
            return false;
        }
        return true;
    }

    public boolean checkStakeholder() throws IOException {
        setStakeholder((StakeholderEntity) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("stakeholder"));
        if (getStakeholder() == null || getStakeholder().getId() == null) {
            setStakeholder(new StakeholderEntity());
           String serverName = ctx.getExternalContext().getRequestServerName();
        int serverPort = (Integer) ctx.getExternalContext().getSessionMap().get("serverPort");
        String contextPath = ctx.getExternalContext().getRequestContextPath();
        ctx.getExternalContext().redirect("http://" + serverName + ":" + serverPort + contextPath + "/stakeholder/StakeholderViewOfferedULPItems.xhtml");
            return false;
        }
        return true;
    }

    public String returnRedemptionStatus(boolean status) {
        if (status == true) {
            return "Voucher Redeemed";
        } else {
            return "Voucher Used";
        }
    }

    // 
    public void retrieveRedemptionInPeriodList(ActionEvent event) throws IOException {
        redemptionInPeriodList = loyaltyProgramSessionBean.getAllRedemptionsByStakeholderIdAndDate(stakeholder.getId(), inputDateFrom, inputDateUntil);
        displayRedemptions = true;
           String serverName = ctx.getExternalContext().getRequestServerName();
        int serverPort = (Integer) ctx.getExternalContext().getSessionMap().get("serverPort");
        String contextPath = ctx.getExternalContext().getRequestContextPath();
        ctx.getExternalContext().redirect("http://" + serverName + ":" + serverPort + contextPath + "/stakeholder/StakeholderViewRedemptions.xhtml");
    }

    // 
    public void retrieveAllRedemptionList(ActionEvent event) throws IOException {
        redemptionInPeriodList = loyaltyProgramSessionBean.getAllRedemptionsByStakeholderId(stakeholder.getId());
        displayRedemptions = true;
        FacesContext.getCurrentInstance().getExternalContext().redirect("stakeholder/StakeholderViewRedemptions.xhtml");
    }

    public String onRowSelectNavigateViewRedemption(SelectEvent event) {
        FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("selectedRedemption", selectedRedemption);
        return "stakeholder/StakeholderViewRedemption?faces-redirect=true";
    }

    public String returnVoucherStatus(RedemptionItemEntity redemption) {
        if (redemption == null) {
            return "Voucher is null !";
        } else {
            if (redemption.getDateUsed() != null) {
                return "Invalid : Voucher has been used";
            } else {
                if (timeIgnoringComparator(redemption.getDateExpired(), new Date()) < 0) {
                    return "Invalid : Voucher has expired";
                } else {
                    return "Valid : Voucher can be used";
                }
            }
        }
    }

    private int timeIgnoringComparator(Date d1, Date d2) {
        if (d1.getYear() != d2.getYear()) {
            return d1.getYear() - d2.getYear();
        }
        if (d1.getMonth() != d2.getMonth()) {
            return d1.getMonth() - d2.getMonth();
        }
        return d1.getDate() - d2.getDate();
    }

    public void declareVoucherAsUsed(ActionEvent event) throws IOException {
        try {
            loyaltyProgramSessionBean.declareVoucherAsUsed(selectedBranch.getId(), selectedVoucher.getId());
            selectedVoucher = null;
            enableRedeemVoucher = false;
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(
                    FacesMessage.SEVERITY_INFO, "Voucher has been declared as Used", ""));
        } catch (Exception e) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(
                    FacesMessage.SEVERITY_ERROR, "An error occurred ! Voucher cannot be declared as Used ! Please try again later", ""));
        }
    }

    public String onRowSelectNavigateULPItemApplication(SelectEvent event) {
        FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("selectedULPItemApplication", getSelectedULPItemApplication());
        return "stakeholder/StakeholderViewULPItemApplication?faces-redirect=true";
    }

    public String onRowSelectNavigateULPItem(SelectEvent event) {
        FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("selectedULPItem", getSelectedULPItem());
        return "stakeholder/StakeholderViewULPItem?faces-redirect=true";
    }

    public void handleULPItemImageUpload(FileUploadEvent event) throws AbortProcessingException, NoSuchAlgorithmException {
        try {
            StakeholderEntity selectedStakeholder = (StakeholderEntity) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("stakeholder");
            System.out.println("Try to upload image");
            System.out.println(event.getFile().getFileName());
            String strDirectory = selectedStakeholder.getUsername();
            String filePath = "C:\\is3102Project\\IS3102Project-war\\web\\images\\upload\\media\\" + strDirectory + "\\ULPItems\\";
            File file = new File(filePath);
            if (!file.exists()) {
                if ((new File(filePath)).mkdirs()) {
                    System.out.println("Directory: " + strDirectory + " created");
                }
            }

            File result = new File(filePath + System.getProperty("file.separator") + event.getFile().getFileName().replace(" ", "_"));
            System.out.println("result: " + result + " created");
            FileOutputStream out = new FileOutputStream(result);
            int a;
            int BUFFER_SIZE = 8192;
            byte[] buffer = new byte[BUFFER_SIZE];
            InputStream is = event.getFile().getInputstream();
            while (true) {
                a = is.read(buffer);
                if (a < 0) {
                    break;
                }
                out.write(buffer, 0, a);
                out.flush();
            }
            getULPItem().setImageURL(strDirectory + "/ULPItems/" + event.getFile().getFileName().replace(" ", "_"));
            out.close();
            is.close();
            FacesMessage msg = new FacesMessage("Succesful " + event.getFile().getFileName() + " is uploaded.");
            FacesContext.getCurrentInstance().addMessage(null, msg);

        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public void validateVoucher(ActionEvent event) throws IOException {
        try {
            List<RedemptionItemEntity> list = loyaltyProgramSessionBean.getVoucherByReferenceNumber(getInputReferenceNumber());
            if (list.isEmpty()) {
                setVoucherExist((Boolean) false);
                enableRedeemVoucher = false;
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(
                        FacesMessage.SEVERITY_ERROR, "Voucher does not exist", ""));
            } else {
                RedemptionItemEntity voucher = list.get(0);
                enableRedeemVoucher = true;
                setSelectedVoucher(voucher);
                setVoucherExist((Boolean) true);
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(
                        FacesMessage.SEVERITY_INFO, "Voucher exists", ""));
                  String serverName = ctx.getExternalContext().getRequestServerName();
        int serverPort = (Integer) ctx.getExternalContext().getSessionMap().get("serverPort");
        String contextPath = ctx.getExternalContext().getRequestContextPath();
        ctx.getExternalContext().redirect("http://" + serverName + ":" + serverPort + contextPath + "/stakeholder/StakeholderValidateVoucher.xhtml");

            }
        } catch (Exception e) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(
                    FacesMessage.SEVERITY_ERROR, "An error occurred ! Voucher information cannot be retrieved ! Please try again later !", ""));
            e.printStackTrace();
        }
    }

    public LoyaltyProgramSessionBean getLoyaltyProgramSessionBean() {
        return loyaltyProgramSessionBean;
    }

    public void setLoyaltyProgramSessionBean(LoyaltyProgramSessionBean loyaltyProgramSessionBean) {
        this.loyaltyProgramSessionBean = loyaltyProgramSessionBean;
    }

    public StakeholderEntity getStakeholder() {
        return stakeholder;
    }

    public void setStakeholder(StakeholderEntity stakeholder) {
        this.stakeholder = stakeholder;
    }

    public RedemptionListEntity getULPItem() {
        return ULPItem;
    }

    public void setULPItem(RedemptionListEntity ULPItem) {
        this.ULPItem = ULPItem;
    }

    public List<RedemptionListEntity> getPendingULPItemApplicationList() {
        return pendingULPItemApplicationList;
    }

    public void setPendingULPItemApplicationList(List<RedemptionListEntity> pendingULPItemApplicationList) {
        this.pendingULPItemApplicationList = pendingULPItemApplicationList;
    }

    public List<RedemptionListEntity> getULPItemApplicationList() {
        return ULPItemApplicationList;
    }

    public void setULPItemApplicationList(List<RedemptionListEntity> ULPItemApplicationList) {
        this.ULPItemApplicationList = ULPItemApplicationList;
    }

    public List<ULPItemHelper> getExpiredULPItemList() {
        return expiredULPItemList;
    }

    public void setExpiredULPItemList(List<ULPItemHelper> expiredULPItemList) {
        this.expiredULPItemList = expiredULPItemList;
    }

    public List<ULPItemHelper> getCurrentULPItemList() {
        return currentULPItemList;
    }

    public void setCurrentULPItemList(List<ULPItemHelper> currentULPItemList) {
        this.currentULPItemList = currentULPItemList;
    }

    public RedemptionListEntity getSelectedULPItemApplication() {
        return selectedULPItemApplication;
    }

    public void setSelectedULPItemApplication(RedemptionListEntity selectedULPItemApplication) {
        this.selectedULPItemApplication = selectedULPItemApplication;
    }

    public ULPItemHelper getSelectedULPItem() {
        return selectedULPItem;
    }

    public void setSelectedULPItem(ULPItemHelper selectedULPItem) {
        this.selectedULPItem = selectedULPItem;
    }

    public boolean isReloadPage() {
        return getReloadPage();
    }

    public void setReloadPage(boolean reloadPage) {
        this.setReloadPage((Boolean) reloadPage);
    }

    public Boolean getReloadPage() {
        return reloadPage;
    }

    public void setReloadPage(Boolean reloadPage) {
        this.reloadPage = reloadPage;
    }

    public String getInputReferenceNumber() {
        return inputReferenceNumber;
    }

    public void setInputReferenceNumber(String inputReferenceNumber) {
        this.inputReferenceNumber = inputReferenceNumber;
    }

    public Boolean getVoucherExist() {
        return voucherExist;
    }

    public void setVoucherExist(Boolean voucherExist) {
        this.voucherExist = voucherExist;
    }

    public RedemptionItemEntity getSelectedVoucher() {
        return selectedVoucher;
    }

    public void setSelectedVoucher(RedemptionItemEntity selectedVoucher) {
        this.selectedVoucher = selectedVoucher;
    }

    public Boolean getEnableRedeemVoucher() {
        return enableRedeemVoucher;
    }

    public void setEnableRedeemVoucher(Boolean enableRedeemVoucher) {
        this.enableRedeemVoucher = enableRedeemVoucher;
    }

    public Date getInputDateFrom() {
        return inputDateFrom;
    }

    public void setInputDateFrom(Date inputDateFrom) {
        this.inputDateFrom = inputDateFrom;
    }

    public Date getInputDateUntil() {
        return inputDateUntil;
    }

    public void setInputDateUntil(Date inputDateUntil) {
        this.inputDateUntil = inputDateUntil;
    }

    public List<RedemptionItemEntity> getRedemptionInPeriodList() {
        return redemptionInPeriodList;
    }

    public boolean getDisplayRedemptions() {
        return displayRedemptions;
    }

    public RedemptionItemEntity getSelectedRedemption() {
        return selectedRedemption;
    }
}
